package managedbean;

import entity.AnalyticsEntity;
import entity.BranchEntity;
import entity.ChosenMetricEntity;
import entity.FnBBranchEntity;
import entity.FnBReservationEntity;
import entity.MealEntity;
import entity.MetricTypeEntity;
import entity.SetMealEntity;
import entity.StakeholderEntity;
import entity.TouristAccountEntity;
import java.io.IOException;
import java.io.Serializable;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.Map;
import javax.ejb.EJB;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.PhaseEvent;
import javax.faces.model.SelectItem;
import org.primefaces.component.chart.series.ChartSeries;
import org.primefaces.component.panel.Panel;
import org.primefaces.event.CloseEvent;
import org.primefaces.event.SelectEvent;
import org.primefaces.model.DashboardColumn;
import org.primefaces.model.DashboardModel;
import org.primefaces.model.DefaultDashboardColumn;
import org.primefaces.model.DefaultDashboardModel;
import org.primefaces.model.chart.CartesianChartModel;
import org.primefaces.model.chart.PieChartModel;
import session.stateful.BranchSessionBeanStateful;
import session.stateful.MealSessionBean;
import session.stateful.MetricSessionBean;
import session.stateful.StakeholderSessionBeanStateful;
import session.stateful.TouristSessionBean;
import util.enumeration.Country;
import util.entityhelper.DoubleComparator;
import util.entityhelper.DoubleHelper;
import util.entityhelper.MetricHelper;
import util.entityhelper.PositionComparator;
import util.entityhelper.SpecialType;


@ManagedBean(name = "metricManagerBean")
@SessionScoped
public class MetricManagerBean implements Serializable {

    @EJB
    private MetricSessionBean basicMetricSessionBean;
    @EJB
    private MealSessionBean mealSessionBean;
    @EJB
    private BranchSessionBeanStateful branchSessionBean;
    @EJB
    private StakeholderSessionBeanStateful stakeholderSessionBean;
    @EJB
    private TouristSessionBean touristSessionBean;
    @EJB
    private MetricSessionBean metricSessionBean;
    private StakeholderEntity selectedStakeholder;
    private boolean initPage;
    private List<DashboardModel> dashboardList;
    private Map<Long, MetricHelper> metricMap;
    private Map<Long, Integer> typeMap;
    private List<MetricTypeEntity> listOfType;
    private int select;
    private DashboardModel selectedDashboard;
    private FacesContext ctx = FacesContext.getCurrentInstance();

    public MetricManagerBean() {
        metricMap = new HashMap<Long, MetricHelper>();
        dashboardList = new ArrayList<DashboardModel>();
        typeMap = new HashMap<Long, Integer>();
        initPage = true;
    }

    public void saveCustomizedList(ActionEvent event) {
        DashboardModel board = dashboardList.get(0);

        metricSessionBean.saveCustomizedList(selectedStakeholder.getId(), board.getColumn(0).getWidgets(), board.getColumn(1).getWidgets());
    }

    public void removeMetricFromList(CloseEvent event) throws IOException {
        System.out.println("Remove");
        System.out.println(event.getSource().getClass());
        Panel panel = (Panel) event.getSource();
        String name = panel.getId();

        removeMetricFromDashboard(select, name);

        long id = Long.valueOf(name.substring(1));
        int pos = typeMap.get(id);

        addMetricToDashboard(pos, name);
        System.out.println("Finish removing");
         String serverName = ctx.getExternalContext().getRequestServerName();
            int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
            String contextPath = ctx.getExternalContext().getRequestContextPath();
            ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/stakeholder/StakeholderAnalytics.xhtml");
    }

    public void addMetricToList(String name) throws IOException {
        System.out.println("Add to list");
        removeMetricFromDashboard(select, name);
        addMetricToDashboard(0, name);
        System.out.println("Finish adding");
  String serverName = ctx.getExternalContext().getRequestServerName();
            int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
            String contextPath = ctx.getExternalContext().getRequestContextPath();
            ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/stakeholder/StakeholderAnalytics.xhtml");
    }

    private void removeMetricFromDashboard(int dashPos, String metricName) {
        DashboardModel board = dashboardList.get(dashPos);
        for (DashboardColumn c : board.getColumns()) {
            if (c.getWidgets().contains(metricName)) {
                c.removeWidget(metricName);
                break;
            }
        }
    }

    private void addMetricToDashboard(int dashPos, String metricName) {
        DashboardModel board = dashboardList.get(dashPos);
        DashboardColumn column1 = board.getColumn(0);
        DashboardColumn column2 = board.getColumn(1);
        if (column1.getWidgetCount() <= column2.getWidgetCount()) {
            column1.addWidget(metricName);
        } else {
            column2.addWidget(metricName);
        }
    }

    /*
     * This method is used to initiate everything for analytics website. Must be used in another
     * webpage rather than the StakeholderAnalytics.xhtml
     */
    public void initAnalytics(PhaseEvent event) {
        //only load this once
        if (initPage) {
            DashboardModel board = new DefaultDashboardModel();
            selectedStakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
            //get list of metric chosen by this stakeholder
            List<ChosenMetricEntity> listOfChosenMetric = metricSessionBean.getListOfChosenMetricByStakeholderId(selectedStakeholder.getId());
            //get all metrics available
            setListOfType(metricSessionBean.getAllMetricType());

            //sort the list according to position of chosen metric in the displayed dashboard
            Collections.sort(listOfChosenMetric, new PositionComparator());
            DashboardColumn column1 = new DefaultDashboardColumn();
            DashboardColumn column2 = new DefaultDashboardColumn();
            //Divide chosen metric into the columns
            for (ChosenMetricEntity m : listOfChosenMetric) {
                if (m.getColumnPosition() == 0) {
                    column1.addWidget("a" + m.getAnalytics().getId());
                } else {
                    column2.addWidget("a" + m.getAnalytics().getId());
                }
                createMetricHelper(m.getAnalytics());
            }

            //each dashboard will have two columns
            board.addColumn(column1);
            board.addColumn(column2);
            //this one is for customized metric as it will be in index 0 of the list
            getDashboardList().add(board);

            //get list of analytics that can be used by this stakeholder. Depends on the highest service
            //package purchased by all of it branches
            List<AnalyticsEntity> allow = metricSessionBean.getAnalyticsCanBeUsedByStakeholder(selectedStakeholder.getId());

            //each metric type will have their corresponding dashboard
            for (int i = 0; i < getListOfType().size(); i++) {
                System.out.println("go now");
                //get all analytics of this type
                List<AnalyticsEntity> listOfAnalytics = metricSessionBean.getAnalyticsByTypeForStakeholder(getListOfType().get(i).getId());
                //create two new columns for this new dashboard
                column1 = new DefaultDashboardColumn();
                column2 = new DefaultDashboardColumn();
                //go through each analytics in this list
                for (AnalyticsEntity ana : listOfAnalytics) {
                    System.out.println("new analytics");
                    //if this analytics can be used by stakeholder
                    if (allow.contains(ana)) {
                        typeMap.put(ana.getId(), i + 1);
                        boolean chosen = false;
                        //check whether this one is already in customized list
                        for (ChosenMetricEntity temp : listOfChosenMetric) {
                            if (temp.getAnalytics().equals(ana)) {
                                chosen = true;
                                break;
                            }
                        }

                        //if not then at this one in this dashboard
                        if (!chosen) {
                            System.out.println("Add new guy");
                            if (column1.getWidgetCount() <= column2.getWidgetCount()) {
                                //create a new id for this Widget because the system
                                //doesn't accept id by number only
                                column1.addWidget("a" + ana.getId());
                            } else {
                                column2.addWidget("a" + ana.getId());
                            }
                            createMetricHelper(ana);
                        }
                    }
                }
                System.out.println("CCCC");
                //refresh the dashboard and add these two columns into it
                board = new DefaultDashboardModel();
                board.addColumn(column1);
                board.addColumn(column2);
                //put it in the list of dashboard
                getDashboardList().add(board);
            }

            //put the customized list at the beginning of the list of dashboard
            //and list of type
            MetricTypeEntity customized = new MetricTypeEntity();
            customized.setName("Customized");
            listOfType.add(0, customized);

            initList(0);
            setSelectedDashboard(dashboardList.get(0));

            //we only load this once
            initPage = false;
        }
    }
    /*
     * Purpose: Change to corresponding dashboard when the user click on the list
     * of metric type on the left hand side
     */

    public void changeMetricType(SelectEvent event) throws IOException {
        System.out.println("change metric type");

        //check the position of this metric type in the list of metric type
        MetricTypeEntity type = (MetricTypeEntity) event.getObject();
        int pos = 0;
        for (; pos < listOfType.size(); pos++) {
            if (type.getName().equals(listOfType.get(pos).getName())) {
                break;
            }
        }
        System.out.println(pos);
        //change the selected position to this position
        setSelect(pos);
        //retrieve the corresponding dashboard
        selectedDashboard = dashboardList.get(pos);
        //try to init all the metrics inside it
        initList(getSelect());
          String serverName = ctx.getExternalContext().getRequestServerName();
            int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
            String contextPath = ctx.getExternalContext().getRequestContextPath();
            ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/stakeholder/StakeholderAnalytics.xhtml");
    }

    private void createMetricHelper(AnalyticsEntity ana) {
        MetricHelper metric = new MetricHelper(ana);
        metricMap.put(ana.getId(), metric);
    }

    public MetricHelper getMetricMap(String name) {
        long id = Long.valueOf(name.substring(1));
        return metricMap.get(id);
    }

    /*
     * Purpose: init all the metrics inside this dashboard
     */
    private void initList(int pos) {
        DashboardModel model = getDashboardList().get(pos);
        for (int i = 0; i < 2; i++) {
            DashboardColumn column1 = model.getColumn(i);
            for (String widget : column1.getWidgets()) {
                initMetric(widget);
            }
        }
    }

    /*
     * Purpose: init this metric. Based on the id of the metric, we
     * must have corresponding method to init it
     */
    private void initMetric(String name) {
        long id = Long.valueOf(name.substring(1));
        if (id == 1) {
            initRankBranch(id);
        }
        if (id == 2) {
            initBestUser(id);
        }
        if (id == 3) {
            initDateReservation(id);
        }

        if (id == 5) {
            initbestProducts(id);
        }
        if (id == 6) {
            initRankStakeholder(id);
        }
        if (id == 7) {
            initMarketShare(id);
        }

        if (id == 8) {
            initBookingGrowth(id);
        }
        if (id == 9) {
            initReturningRate(id);
        }
        if (id == 10) {
            initUpsellingRate(id);
        }

        if (id == 50) {
            initAcquisitionRateLocal(id);
        }
        if (id == 51) {
            initAcquisitionRateTourist(id);
        }
        if (id == 52) {
            initTopProductsStakeholder(id);
        }
        if (id == 53) {
            initCustomerSpending(id);
        }
        if (id == 54) {
            initCustomerValue(id);
        }
    }


    /*
     * Purpose: Compute the metrics that required users to input value.
     * Based on the id of metric, we will have corresponding methods
     */
    public void compute(String name) throws IOException {
        long id = Long.valueOf(name.substring(1));

        if (id == 2) {
            computeBestUser(id);
        }
        if (id == 3) {
            computeDateReservation(id);
        }

        if (id == 5) {
            computeBestProducts(id);
        }
        if (id == 7) {
            computeMarketShare(id);
        }

        if (id == 8) {
            computeBookingGrowth(id);
        }
        if (id == 9) {
            computeReturningRate(id);
        }

        if (id == 50) {
            computeAcquisitionRateLocal(id);
        }
        if (id == 51) {
            computeAcquisitionRateTourist(id);
        }
        if (id == 52) {
            computeTopProductsStakeholder(id);
        }
        if (id == 53) {
            computeCustomerSpending(id);
        }
        if (id == 54) {
            computeCustomerValue(id);
        }
         String serverName = ctx.getExternalContext().getRequestServerName();
            int serverPort = (Integer) ctx.getExternalContext().getSessionMap().get("serverPort");
            String contextPath = ctx.getExternalContext().getRequestContextPath();
            ctx.getExternalContext().redirect("http://" + serverName + ":" + serverPort + contextPath + "/stakeholder/StakeholderAnalytics.xhtml");
    }

    private void initRankBranch(long id) {
        MetricHelper metric = metricMap.get(id);
        if (!metric.isInit()) {
            //calculation
            List<BranchEntity> branch = new ArrayList<BranchEntity>();
            List<FnBBranchEntity> fnBBranch = new ArrayList<FnBBranchEntity>();

            branch = branchSessionBean.getAllBranchByStakeholderId(selectedStakeholder.getId());
            //get fandBBranch only
            for (BranchEntity b : branch) {
                if (b instanceof FnBBranchEntity) {
                    FnBBranchEntity f = (FnBBranchEntity) b;
                    fnBBranch.add(f);
                }
            }
            List<DoubleHelper> list = new ArrayList<DoubleHelper>();
            //Put branch and revenue
            for (FnBBranchEntity f : fnBBranch) {
                List<FnBReservationEntity> fnBReservation = new ArrayList<FnBReservationEntity>();
                List<String> reservationNumbers = new ArrayList<String>();
                Double count = 0.0;
                fnBReservation = basicMetricSessionBean.fnBReservation(f.getId());
                reservationNumbers = basicMetricSessionBean.reservationNumbers(fnBReservation);
                count = Double.valueOf(reservationNumbers.get(6));
                list.add(new DoubleHelper(f, count));
            }

            Collections.sort(list, new DoubleComparator());

            List<SpecialType> tempList = new ArrayList<SpecialType>();
            SpecialType type = new SpecialType();
            type.addValue("Branch Id");
            type.addValue("Branch Name");
            type.addValue("Revenue");
            tempList.add(type);

            for (int i = 0; i < list.size(); i++) {
                type = new SpecialType();
                DoubleHelper helper = list.get(i);
                FnBBranchEntity tempBranch = (FnBBranchEntity) helper.getObject();
                type.addValue(tempBranch.getId() + "");
                type.addValue(tempBranch.getBranchName());
                type.addValue(helper.getDoubleNum() + "");
                tempList.add(type);
            }
            metric.addDataTable(tempList, "Ranking of branches");
            metric.setInit(true);
        }
    }
    //Duy-start

    private void initAcquisitionRateLocal(long id) {
        MetricHelper metric = metricMap.get(id);

        if (!metric.isInit()) {
            metric.setCompute(true);
            metric.addDateList("From");
            metric.addDateList("To ");
            selectedStakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
            metric.setInit(true);
        }
    }

    private void computeAcquisitionRateLocal(long id) {
        MetricHelper metric = metricMap.get(id);
        PieChartModel pieChart = new PieChartModel();
        int numLocalReserve;
        int numLocalTotal;

        Date date1 = metric.getDateList();
        Date date2 = metric.getDateList();
        numLocalReserve = touristSessionBean.getDistinctLocalAccountOfStakeholder(selectedStakeholder, date1, date2).size();
        System.out.println("numLocalReserve " + numLocalReserve);
        numLocalTotal = touristSessionBean.getAllLocalAccount().size();
        System.out.println("numLocalTotal " + numLocalTotal);
        //setPieChart
        pieChart.set("Your local Customer", numLocalReserve);
        pieChart.set("Competitors's local Customer", numLocalTotal - numLocalReserve);
        metric.setModel(pieChart);
    }

    private void initAcquisitionRateTourist(long id) {
        MetricHelper metric = metricMap.get(id);

        if (!metric.isInit()) {
            metric.setCompute(true);
            metric.addDateList("From");
            metric.addDateList("To ");
            selectedStakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
            metric.setInit(true);
        }
    }

    private void computeAcquisitionRateTourist(long id) {
        MetricHelper metric = metricMap.get(id);
        PieChartModel pieChart = new PieChartModel();
        int numTouristReserve;
        int numTouristTotal;

        Date date1 = metric.getDateList();
        Date date2 = metric.getDateList();
        numTouristReserve = touristSessionBean.getDistinctTouristAccountOfStakeholder(selectedStakeholder, date1, date2).size();
        System.out.println("numTouristReserve " + numTouristReserve);
        numTouristTotal = touristSessionBean.getAllTouristAccount().size();
        System.out.println("numTouristTotal " + numTouristTotal);
        //setPieChart
        pieChart.set("Your Foreign Customer", numTouristReserve);
        pieChart.set("Competitors's Foreign Customer", numTouristTotal - numTouristReserve);
        metric.setModel(pieChart);
    }

    private void initTopProductsStakeholder(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.setCompute(true);
        if (!metric.isInit()) {
            selectedStakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");

            metric.setInit(true);
        }
    }

    private void computeTopProductsStakeholder(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.resetDataTable();
        HashMap<MealEntity, Double> map = new HashMap<MealEntity, Double>();
        List<MealEntity> mealList = new ArrayList<MealEntity>();
        mealList = mealSessionBean.getMealListOfStakeholder(selectedStakeholder);
        //Arrage meal ID and  quantity
        for (int i = 0; i < mealList.size(); i++) {
            int count = 0;
            for (int j = 0; j < mealList.get(i).getReservedMeal().size(); j++) {
                count = count + mealList.get(i).getReservedMeal().get(j).getQuantity();
            }
            map.put(basicMetricSessionBean.getMealById(mealList.get(i).getId()), count * 1.0);
        }

        //sort
        List<DoubleHelper> list = new ArrayList<DoubleHelper>();
        for (MealEntity meal : map.keySet()) {
            list.add(new DoubleHelper(meal, map.get(meal)));
        }
        Collections.sort(list, new DoubleComparator());

        List<SpecialType> tempList = new ArrayList<SpecialType>();
        SpecialType type = new SpecialType();
        type.addValue("Meal Id");
        type.addValue("Meal Name");
        type.addValue("Quantity");
        tempList.add(type);

        for (int i = 0; i < Math.min(5, list.size()); i++) {
            type = new SpecialType();
            DoubleHelper helper = list.get(i);
            MealEntity m = (MealEntity) helper.getObject();
            type.addValue(m.getId() + "");
            type.addValue(m.getName());
            int temp = helper.getDoubleNum().intValue();
            type.addValue(temp + "");
            tempList.add(type);
        }
        metric.addDataTable(tempList, "Top Meals");


        /* code for set meal*/
        List<SetMealEntity> setMealList = new ArrayList<SetMealEntity>();
        setMealList = mealSessionBean.getSetMealListOfStakeholder(selectedStakeholder);
        HashMap<SetMealEntity, Double> map1 = new HashMap<SetMealEntity, Double>();
        for (int i = 0; i < setMealList.size(); i++) {
            int count = 0;
            for (int j = 0; j < setMealList.get(i).getReservedSetMeal().size(); j++) {
                count = count + setMealList.get(i).getReservedSetMeal().get(j).getQuantity();
            }
            map1.put(basicMetricSessionBean.getSetMealById(setMealList.get(i).getId()), count * 1.0);
        }
        //sort
        List<DoubleHelper> list1 = new ArrayList<DoubleHelper>();
        for (SetMealEntity setmeal : map1.keySet()) {
            list1.add(new DoubleHelper(setmeal, map1.get(setmeal)));
        }
        Collections.sort(list1, new DoubleComparator());

        List<SpecialType> tempList1 = new ArrayList<SpecialType>();
        type = new SpecialType();
        type.addValue("Set Meal Id");
        type.addValue("Set Meal Name");
        type.addValue("Quantity");
        tempList1.add(type);

        for (int i = 0; i < Math.min(3, list1.size()); i++) {
            type = new SpecialType();
            DoubleHelper helper = list1.get(i);
            SetMealEntity sm = (SetMealEntity) helper.getObject();
            type.addValue(sm.getId() + "");
            type.addValue(sm.getName());
            int temp = helper.getDoubleNum().intValue();
            type.addValue(temp + "");
            tempList1.add(type);
        }
        metric.addDataTable(tempList1, "Top Set Meals");
    }

    private void initCustomerSpending(long id) {
        MetricHelper metric = metricMap.get(id);
        if (!metric.isInit()) {
            selectedStakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
            metric.setCompute(true);
            metric.addDateList("From");
            metric.addDateList("To ");
            metric.setInit(true);
        }
    }

    private void computeCustomerSpending(long id) {
        MetricHelper metric = metricMap.get(id);
        CartesianChartModel cartesianModel;
        cartesianModel = new CartesianChartModel();
        ChartSeries customerSpending = new ChartSeries();
        int count1 = 0, count2 = 0, count3 = 0, count4 = 0, count5 = 0;
        List<Double> customerSpendingList = new ArrayList<Double>();
        int i, j;
        Date date1 = metric.getDateList();
        Date date2 = metric.getDateList();

        System.out.println("1");
        customerSpendingList = touristSessionBean.getCustomerSpendingList(selectedStakeholder, date1, date2);
        System.out.println("2");
        for (i = 0; i < customerSpendingList.size(); i++) {
            Double tempSpending;
            Double temp = 0.0;
            tempSpending = customerSpendingList.get(i);
            System.out.println("tempSpending " + tempSpending);
            if (tempSpending < 25.0) {
                count1++;
            }
            if (tempSpending >= 25 && tempSpending < 50) {
                count2++;
            }
            if (tempSpending >= 50 && tempSpending < 75) {
                count3++;
            }
            if (tempSpending >= 75 && tempSpending < 100) {
                count4++;
            }
            if (tempSpending >= 100) {
                count5++;
            }
        }
        System.out.println("3");
        customerSpending.setLabel("No. of resevations");
        customerSpending.set("> $100", count5);
        customerSpending.set("$75-$100", count4);
        customerSpending.set("$50-$75", count3);
        customerSpending.set("$25-$50", count2);
        customerSpending.set("$0-$25", count1);

        cartesianModel.addSeries(customerSpending);
        metric.setModel(cartesianModel);
    }

    private void initCustomerValue(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.setCompute(true);
        if (!metric.isInit()) {
            selectedStakeholder = (StakeholderEntity) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("stakeholder");
            metric.addDateList("From");
            metric.addDateList("To ");
            metric.setInit(true);
        }
    }

    private void computeCustomerValue(long id) {
        MetricHelper metric = metricMap.get(id);
        List<Double> customerSpendingList = new ArrayList<Double>();
        Double averageSpending = 0.0;
        Double totalSpending = 0.0;

        Date date1 = metric.getDateList();
        Date date2 = metric.getDateList();

        customerSpendingList = touristSessionBean.getCustomerSpendingList(selectedStakeholder, date1, date2);
        System.out.println("AAAAA" + customerSpendingList.size());
        for (int i = 0; i < customerSpendingList.size(); i++) {
            totalSpending += customerSpendingList.get(i);
        }
        averageSpending = totalSpending / customerSpendingList.size();

        //average Interval
        Double averageIntervalLocal;
        Double averageIntervalTourist;
        averageIntervalLocal = touristSessionBean.getAverageReservationIntervalLocal(selectedStakeholder);
        averageIntervalTourist = touristSessionBean.getAverageReservationIntervalTourist(selectedStakeholder);

        //averageNumReservation
        Double averageNumReservationLocal;
        Double averageNumReservationTourist;
        averageNumReservationLocal = touristSessionBean.getAverageNumReservationLocal(selectedStakeholder);
        averageNumReservationTourist = touristSessionBean.getAverageNumReservationTourist(selectedStakeholder);

        //add to metricHelper
        metric.resetOutputValue();
        metric.addOutputValue("Average Spending per Reservation ($): ", averageSpending.toString());
        metric.addOutputValue("Average Number of Reservations per Local Customer: ", averageNumReservationLocal.toString());
        metric.addOutputValue("Average Number of Reservations per Tourist: ", averageNumReservationTourist.toString());
        metric.addOutputValue("Average Time Between Reservations of a Local Customer (Day): ", averageIntervalLocal.toString());
        metric.addOutputValue("Average Time Between Reservations of a Tourist (Day): ", averageIntervalTourist.toString());
    }

//Duy-end
    public List<DashboardModel> getDashboardList() {
        return dashboardList;
    }

    public void setDashboardList(List<DashboardModel> dashboardList) {
        this.dashboardList = dashboardList;
    }

    public List<MetricTypeEntity> getListOfType() {
        return listOfType;
    }

    public void setListOfType(List<MetricTypeEntity> listOfType) {
        this.listOfType = listOfType;
    }

    public DashboardModel getSelectedDashboard() {
        return selectedDashboard;
    }

    public void setSelectedDashboard(DashboardModel selectedDashboard) {
        this.selectedDashboard = selectedDashboard;
    }

    public int getSelect() {
        return select;
    }

    public void setSelect(int select) {
        this.select = select;
    }

    /*Hieu start Nov 1
     * 
     */
    // Best user - start 
    private void initBestUser(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.setCompute(true);
        if (!metric.isInit()) {
            List<BranchEntity> branch = new ArrayList<BranchEntity>();
            List<FnBBranchEntity> fnBBranch = new ArrayList<FnBBranchEntity>();

            branch = branchSessionBean.getAllBranchByStakeholderId(selectedStakeholder.getId());
            //get fandBBranch only
            for (BranchEntity b : branch) {
                if (b instanceof FnBBranchEntity) {
                    FnBBranchEntity f = (FnBBranchEntity) b;
                    fnBBranch.add(f);
                }
            }
            //declare select list
            List selectList;
            selectList = new ArrayList<SelectItem>();
            for (int i = 0; i < fnBBranch.size(); i++) {
                selectList.add(new SelectItem(i, fnBBranch.get(i).getBranchName()));
            }

            metric.addSelectList(selectList, "BranchNameList");

            metric.setInit(true);
        }
    }

    private void computeBestUser(long id) {

        MetricHelper metric = metricMap.get(id);
        metric.resetDataTable();
        List<BranchEntity> branch = new ArrayList<BranchEntity>();
        List<FnBBranchEntity> fnBBranch = new ArrayList<FnBBranchEntity>();

        branch = branchSessionBean.getAllBranchByStakeholderId(selectedStakeholder.getId());
        //get fandBBranch only
        for (BranchEntity b : branch) {
            if (b instanceof FnBBranchEntity) {
                FnBBranchEntity f = (FnBBranchEntity) b;
                fnBBranch.add(f);
            }
        }

        FnBBranchEntity selectedBranch = fnBBranch.get(metric.getSelectVar());
        HashMap<Long, Double> map = new HashMap<Long, Double>();
        List<FnBReservationEntity> list1 = new ArrayList<FnBReservationEntity>();
        List<FnBReservationEntity> list2 = new ArrayList<FnBReservationEntity>();
        list1 = basicMetricSessionBean.fnBReservation(selectedBranch.getId());
        for (int i = 0; i < list1.size(); i++) {
            if (list1.get(i).getStatus() != null && list1.get(i).getStatus().equalsIgnoreCase("Show")) {
                list2.add(list1.get(i));
            }
        }
        //Arrage tourist ID and according deposit
        for (int i = 0; i < list2.size(); i++) {
            Long tempId = list2.get(i).getTourist().getId();
            if (!map.containsKey(tempId)) {
                map.put(tempId, list2.get(i).getDeposit());
            } else {
                Double value = map.get(tempId) + list2.get(i).getDeposit();
                map.put(tempId, value);
            }
        }

        List<DoubleHelper> list = new ArrayList<DoubleHelper>();
        //Put branch and revenue


        for (Long tempId : map.keySet()) {
            System.out.println("Tourist ID is " + tempId);
            System.out.println("2A");
            list.add(new DoubleHelper(basicMetricSessionBean.getTouristById(tempId), map.get(tempId)));
            System.out.println("2B");
        }
        Collections.sort(list, new DoubleComparator());

        List<SpecialType> tempList = new ArrayList<SpecialType>();
        SpecialType type = new SpecialType();
        type.addValue("Customer Id");
        type.addValue("Customer Name");
        type.addValue("Deposit");
        tempList.add(type);

        for (int i = 0; i < Math.min(5, list.size()); i++) {
            type = new SpecialType();
            DoubleHelper helper = list.get(i);
            TouristAccountEntity t = (TouristAccountEntity) helper.getObject();
            type.addValue(t.getId() + "");
            type.addValue(t.getTourist().getFirstName() + " " + t.getTourist().getLastName());
            System.out.println("ID is " + t.getId());
            type.addValue(helper.getDoubleNum() + "");
            tempList.add(type);
        }
        metric.addDataTable(tempList, "List of best users");

    }
    //Best User - end

    private void initDateReservation(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.setCompute(true);
        if (!metric.isInit()) {
            List<BranchEntity> branch = new ArrayList<BranchEntity>();
            List<FnBBranchEntity> fnBBranch = new ArrayList<FnBBranchEntity>();

            branch = branchSessionBean.getAllBranchByStakeholderId(selectedStakeholder.getId());
            //get fandBBranch only
            for (BranchEntity b : branch) {
                if (b instanceof FnBBranchEntity) {
                    FnBBranchEntity f = (FnBBranchEntity) b;
                    fnBBranch.add(f);
                }
            }
            List selectList;
            selectList = new ArrayList<SelectItem>();
            selectList.add(new SelectItem(0, "Period Reservation"));
            selectList.add(new SelectItem(1, "Date Reservation"));
            metric.addSelectList(selectList, "Type list");
            //make branch list

            selectList = new ArrayList<SelectItem>();
            for (int i = 0; i < fnBBranch.size(); i++) {
                selectList.add(new SelectItem(i, fnBBranch.get(i).getBranchName()));
            }

            metric.addSelectList(selectList, "Branch Name List ");
            //

            metric.setInit(true);
        }
    }

    private void computeDateReservation(long id) {
        MetricHelper metric = metricMap.get(id);
        int currentValue = metric.getSelectVar();
        int previousValue = metric.getPreviousValue();
        metric.resetDataTable();

        List<BranchEntity> branch = new ArrayList<BranchEntity>();
        List<FnBBranchEntity> fnBBranch = new ArrayList<FnBBranchEntity>();
        branch = branchSessionBean.getAllBranchByStakeholderId(selectedStakeholder.getId());
        //get fandBBranch only
        for (BranchEntity b : branch) {
            if (b instanceof FnBBranchEntity) {
                FnBBranchEntity f = (FnBBranchEntity) b;
                fnBBranch.add(f);
            }
        }
        FnBBranchEntity selectedBranch = fnBBranch.get(metric.getSelectVar());
        System.out.println("ABC1");
        //0 for period reservation
        //1 for date reservation
        if (currentValue != previousValue) {
            metric.setPreviousValue(currentValue);
            metric.resetDateList();
            if (currentValue == 0) {
                metric.addDateList("From ");
                metric.addDateList("To ");
            }

            if (currentValue == 1) {
                metric.addDateList("Date ");
            }
        } else {
            if (currentValue == 0) {
                Date date1 = metric.getDateList();
                Date date2 = metric.getDateList();
                Date date_use = new Date(date1.getTime());

                List<String> result = new ArrayList<String>();
                int total = 0, show = 0, noshow = 0, confirmed = 0, rejected = 0, cancelled = 0;
                Double deposit = 0.0, revenue = 0.0;

                while (date_use.compareTo(date2) <= 0) {
                    System.out.println("A");
                    List<FnBReservationEntity> list = new ArrayList<FnBReservationEntity>();
                    list = basicMetricSessionBean.dateReservation(date_use, selectedBranch.getId());
                    if (!list.isEmpty()) {
                        System.out.println("B");
                        result = new ArrayList<String>();
                        result = basicMetricSessionBean.reservationNumbers(list);
                        total = total + Integer.valueOf(result.get(0));
                        show = show + Integer.valueOf(result.get(1));
                        noshow = noshow + Integer.valueOf(result.get(2));
                        confirmed = confirmed + Integer.valueOf(result.get(3));
                        rejected = rejected + Integer.valueOf(result.get(4));
                        cancelled = cancelled + Integer.valueOf(result.get(7));
                        deposit = deposit + Double.valueOf(result.get(5));
                        revenue = revenue + Double.valueOf(result.get(6));
                    }
                    date_use.setTime(date_use.getTime() + 1 * 24 * 60 * 60 * 1000);
                }

                //add table
                List<SpecialType> tempList = new ArrayList<SpecialType>();
                SpecialType type = new SpecialType();
                type.addValue("Name");
                type.addValue("Value");
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Total Reservation ");
                type.addValue(String.valueOf(total));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Show ");
                type.addValue(String.valueOf(show));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("No Show ");
                type.addValue(String.valueOf(noshow));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Confirmed Reservation ");
                type.addValue(String.valueOf(confirmed));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Rejected Reservation ");
                type.addValue(String.valueOf(rejected));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Cancelled Reservation ");
                type.addValue(String.valueOf(cancelled));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Customers' deposits ");
                type.addValue(String.valueOf(deposit));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Revenue ");
                type.addValue(String.valueOf(revenue));
                tempList.add(type);
                metric.addDataTable(tempList, "Period reservation statistics");
            } else {
                Date date = metric.getDateList();
                //start calculation
                List<String> result = new ArrayList<String>();
                List<FnBReservationEntity> list = new ArrayList<FnBReservationEntity>();
                list = basicMetricSessionBean.dateReservation(date, selectedBranch.getId());
                if (!list.isEmpty()) {
                    result = basicMetricSessionBean.reservationNumbers(list);
                } else {
                    result.add("0");
                    result.add("0");
                    result.add("0");
                    result.add("0");
                    result.add("0");
                    result.add("0");
                    result.add("0");
                    result.add("0");
                }

                // end calculation
                //add table
                List<SpecialType> tempList = new ArrayList<SpecialType>();
                SpecialType type = new SpecialType();
                type.addValue("Name");
                type.addValue("Value");
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Total Reservation ");
                type.addValue(result.get(0));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Show ");
                type.addValue(result.get(1));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("No Show ");
                type.addValue(result.get(2));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Confirmed Reservation ");
                type.addValue(result.get(3));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Rejected Reservation ");
                type.addValue(result.get(4));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Cancelled Reservation ");
                type.addValue(result.get(7));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Customers' deposits ");
                type.addValue(result.get(5));
                tempList.add(type);

                type = new SpecialType();
                type.addValue("Revenue ");
                type.addValue(result.get(6));
                tempList.add(type);
                metric.addDataTable(tempList, "Statistics about reservation");
            }
        }
    }

    //best Products
    private void initbestProducts(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.setCompute(true);
        if (!metric.isInit()) {
            List<BranchEntity> branch = new ArrayList<BranchEntity>();
            List<FnBBranchEntity> fnBBranch = new ArrayList<FnBBranchEntity>();

            branch = branchSessionBean.getAllBranchByStakeholderId(selectedStakeholder.getId());
            //get fandBBranch only
            for (BranchEntity b : branch) {
                if (b instanceof FnBBranchEntity) {
                    FnBBranchEntity f = (FnBBranchEntity) b;
                    fnBBranch.add(f);
                }
            }
            //make branch list
            List selectList;
            selectList = new ArrayList<SelectItem>();
            for (int i = 0; i < fnBBranch.size(); i++) {
                selectList.add(new SelectItem(i, fnBBranch.get(i).getBranchName()));
            }

            metric.addSelectList(selectList, "Branch Name List ");
            metric.setInit(true);
        }
    }

    private void computeBestProducts(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.resetDataTable();
        List<BranchEntity> branch = new ArrayList<BranchEntity>();
        List<FnBBranchEntity> fnBBranch = new ArrayList<FnBBranchEntity>();
        branch = branchSessionBean.getAllBranchByStakeholderId(selectedStakeholder.getId());
        //get fandBBranch only
        for (BranchEntity b : branch) {
            if (b instanceof FnBBranchEntity) {
                FnBBranchEntity f = (FnBBranchEntity) b;
                fnBBranch.add(f);
            }
        }
        FnBBranchEntity selectedBranch = fnBBranch.get(metric.getSelectVar());

        List<MealEntity> mealList = new ArrayList<MealEntity>();
        mealList = mealSessionBean.getMealListOfABranch(selectedBranch.getId());
        HashMap<MealEntity, Double> map = new HashMap<MealEntity, Double>();
        //Arrage meal ID and  quantity
        for (int i = 0; i < mealList.size(); i++) {
            int count = 0;
            for (int j = 0; j < mealList.get(i).getReservedMeal().size(); j++) {
                count = count + mealList.get(i).getReservedMeal().get(j).getQuantity();
            }
            map.put(basicMetricSessionBean.getMealById(mealList.get(i).getId()), count * 1.0);
        }

        //sort
        List<DoubleHelper> list = new ArrayList<DoubleHelper>();
        for (MealEntity meal : map.keySet()) {
            list.add(new DoubleHelper(meal, map.get(meal)));
        }
        Collections.sort(list, new DoubleComparator());

        List<SpecialType> tempList = new ArrayList<SpecialType>();
        SpecialType type = new SpecialType();
        type.addValue("Meal Id");
        type.addValue("Meal Name");
        type.addValue("Quantity");
        tempList.add(type);

        for (int i = 0; i < Math.min(5, list.size()); i++) {
            type = new SpecialType();
            DoubleHelper helper = list.get(i);
            MealEntity m = (MealEntity) helper.getObject();
            type.addValue(m.getId() + "");
            type.addValue(m.getName());
            type.addValue(helper.getDoubleNum() + "");
            tempList.add(type);
        }
        metric.addDataTable(tempList, "Best Meals");

        /* code for set meal*/
        List<SetMealEntity> setMealList = new ArrayList<SetMealEntity>();
        setMealList = mealSessionBean.getSetMealListOfABranch(selectedBranch.getId());
        HashMap<SetMealEntity, Double> map1 = new HashMap<SetMealEntity, Double>();
        for (int i = 0; i < setMealList.size(); i++) {
            int count = 0;
            for (int j = 0; j < setMealList.get(i).getReservedSetMeal().size(); j++) {
                count = count + setMealList.get(i).getReservedSetMeal().get(j).getQuantity();
            }
            map1.put(basicMetricSessionBean.getSetMealById(setMealList.get(i).getId()), count * 1.0);
        }

        //sort
        List<DoubleHelper> list1 = new ArrayList<DoubleHelper>();
        for (SetMealEntity setmeal : map1.keySet()) {
            list1.add(new DoubleHelper(setmeal, map1.get(setmeal)));
        }
        Collections.sort(list1, new DoubleComparator());

        List<SpecialType> tempList1 = new ArrayList<SpecialType>();
        type = new SpecialType();
        type.addValue("Set Meal Id");
        type.addValue("Set Meal Name");
        type.addValue("Quantity");
        tempList1.add(type);

        for (int i = 0; i < Math.min(3, list1.size()); i++) {
            type = new SpecialType();
            DoubleHelper helper = list1.get(i);
            SetMealEntity sm = (SetMealEntity) helper.getObject();
            type.addValue(sm.getId() + "");
            type.addValue(sm.getName());
            type.addValue(helper.getDoubleNum() + "");
            tempList1.add(type);
        }
        metric.addDataTable(tempList1, "Best Set Meals");
    }

    //Rank Stakeholder
    private void initRankStakeholder(long id) {
        MetricHelper metric = metricMap.get(id);
        if (!metric.isInit()) {
            List<StakeholderEntity> stakeholder = new ArrayList<StakeholderEntity>();
            stakeholder = stakeholderSessionBean.getAllStakeholders();
            HashMap<StakeholderEntity, Double> map = new HashMap<StakeholderEntity, Double>();
            //put stakeholder and revenue
            for (StakeholderEntity s : stakeholder) {
                List<BranchEntity> branch = new ArrayList<BranchEntity>();
                Double count = 0.0;
                branch = branchSessionBean.getAllBranchByStakeholderId(s.getId());
                System.out.println("count: " + count);
                for (BranchEntity b : branch) {
                    if (b instanceof FnBBranchEntity) {
                        FnBBranchEntity f = (FnBBranchEntity) b;                        
                        List<FnBReservationEntity> fnBReservation = basicMetricSessionBean.fnBReservation(f.getId());
                        List<String> reservationNumbers = basicMetricSessionBean.reservationNumbers(fnBReservation);
                        count = count + Double.valueOf(reservationNumbers.get(6));
                    }
                }
                System.out.println("count: " + count);
                //if (Long.compare(s.getId(),selectedStakeholder.getId())==0) selectedCount=count;
                //above line is to get position of selected Stakeholder in the sorted list.
                map.put(s, count);
            }

            List<DoubleHelper> list = new ArrayList<DoubleHelper>();
            for (StakeholderEntity s : map.keySet()) {
                list.add(new DoubleHelper(s, map.get(s)));
            }
            Collections.sort(list, new DoubleComparator());

            List<SpecialType> tempList = new ArrayList<SpecialType>();
            SpecialType type = new SpecialType();
            type.addValue("Revenue ($)");
            tempList.add(type);

            for (int i = 0; i < Math.min(10, list.size()); i++) {
                type = new SpecialType();
                DoubleHelper helper = list.get(i);
                type.addValue(helper.getDoubleNum() + "");
                tempList.add(type);
            }
            metric.addDataTable(tempList, "Stakeholder");
            metric.setInit(true);
        }
    }

    //Market share
    private void initMarketShare(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.setCompute(true);
        if (!metric.isInit()) {
            List selectList;

            selectList = new ArrayList<SelectItem>();
            selectList.add(new SelectItem(0, "All time Market Share"));
            selectList.add(new SelectItem(1, "Period Market Share"));
            metric.addSelectList(selectList, "Type list");

            metric.setInit(true);
        }
    }

    private void computeMarketShare(long id) {
        MetricHelper metric = metricMap.get(id);
        int currentValue = metric.getSelectVar();
        int previousValue = metric.getPreviousValue();
        // 0: all time market share
        //1: period market share
        if ((currentValue != previousValue && previousValue != - 1)) {
            metric.setPreviousValue(currentValue);
            metric.setModel(null);
            if (currentValue == 0) {
                metric.resetDateList();
            }
            if (currentValue == 1) {
                metric.addDateList("From ");
                metric.addDateList("To ");
            }
            System.out.println("change type");
        } else {
            System.out.println("compute");
            if (currentValue == 0) {
                if (previousValue == -1) {
                    metric.setPreviousValue(0);
                }
                PieChartModel pieChart = new PieChartModel();


                List<StakeholderEntity> stakeholder = new ArrayList<StakeholderEntity>();
                stakeholder = stakeholderSessionBean.getAllStakeholders();
                Double allCount = 0.0;
                Double selectedCount = 0.0;
                for (StakeholderEntity s : stakeholder) {
                    List<BranchEntity> branch = new ArrayList<BranchEntity>();
                    Double count = 0.0;
                    branch = branchSessionBean.getAllBranchByStakeholderId(s.getId());
                    System.out.println("count: " + count);
                    for (BranchEntity b : branch) {
                        if (b instanceof FnBBranchEntity) {
                            FnBBranchEntity f = (FnBBranchEntity) b;
                            List<FnBReservationEntity> fnBReservation = new ArrayList<FnBReservationEntity>();
                            List<String> reservationNumbers = new ArrayList<String>();
                            fnBReservation = metricSessionBean.fnBReservation(f.getId());
                            reservationNumbers = metricSessionBean.reservationNumbers(fnBReservation);
                            count = count + Double.valueOf(reservationNumbers.get(6));
                        }
                    }
                    System.out.println("count: " + count);

                    if (s.getId() == selectedStakeholder.getId()) {
                        selectedCount = count;
                        System.out.println("selectedCount: " + selectedCount);
                    }

                    allCount = allCount + count;
                }
                pieChart.set("Other Competitors", allCount - selectedCount);
                pieChart.set(stakeholderSessionBean.getStakeholderById(selectedStakeholder.getId()).getCorpName(), selectedCount);

                metric.setModel(pieChart);
            } else {
                PieChartModel pieChart = new PieChartModel();
                Date date1 = metric.getDateList();
                Date date2 = metric.getDateList();
                Date date_use = new Date(date1.getTime());
                Double allCount = 0.0;
                Double selectedCount = 0.0;

                while (date_use.compareTo(date2) <= 0) {
                    List<StakeholderEntity> stakeholder = new ArrayList<StakeholderEntity>();
                    stakeholder = stakeholderSessionBean.getAllStakeholders();
                    //revenue of stakeholder in one day
                    for (StakeholderEntity s : stakeholder) {
                        List<BranchEntity> branch = new ArrayList<BranchEntity>();
                        Double count = 0.0; //revenue of one stakeholder
                        branch = branchSessionBean.getAllBranchByStakeholderId(s.getId());
                        System.out.println("count: " + count);
                        for (BranchEntity b : branch) {
                            //add up each branch revenue
                            if (b instanceof FnBBranchEntity) {
                                FnBBranchEntity f = (FnBBranchEntity) b;
                                List<FnBReservationEntity> fnBReservation = new ArrayList<FnBReservationEntity>();
                                List<String> reservationNumbers = new ArrayList<String>();
                                fnBReservation = metricSessionBean.dateReservation(date_use, f.getId());
                                reservationNumbers = metricSessionBean.reservationNumbers(fnBReservation);
                                count = count + Double.valueOf(reservationNumbers.get(6));
                            }
                        }
                        if (s.getId() == selectedStakeholder.getId()) {
                            selectedCount = selectedCount + count;
                            System.out.println("selectedCount: " + selectedCount);
                        }
                        allCount = allCount + count;
                        System.out.println("allCount: " + allCount);
                    }
                    date_use.setTime(date_use.getTime() + 1 * 24 * 60 * 60 * 1000);
                }

                System.out.println("set piechart");

                pieChart.set("Other Competitors", allCount - selectedCount);  //allCount-selectedCount
                pieChart.set(stakeholderSessionBean.getStakeholderById(selectedStakeholder.getId()).getCorpName(), selectedCount);

                metric.setModel(pieChart);
            }
        }
    }

    //booking growth
    private void initBookingGrowth(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.setCompute(true);
        if (!metric.isInit()) {
            metric.addDateList("From the month of ");
            metric.addDateList("To the month of ");
            List selectList;
            selectList = new ArrayList<SelectItem>();
            selectList.add(new SelectItem(0, "Booking Growth"));
            selectList.add(new SelectItem(1, "Revenue Growth"));
            metric.addSelectList(selectList, "Type list");
            metric.setInit(true);
        }
    }

    private void computeBookingGrowth(long id) {
        System.out.println("A");
        MetricHelper metric = metricMap.get(id);

        Date date1_use, date2_use;
        Date date1, date2;

        date1 = metric.getDateList();
        date2 = metric.getDateList();
        int currentValue = metric.getSelectVar();

        int month1 = date1.getMonth();
        int year1 = date1.getYear();

        int month2 = date2.getMonth();
        int year2 = date2.getYear();
        System.out.println("B");
        date1_use = new Date(Integer.valueOf(year1), Integer.valueOf(month1), 1);
        System.out.println("Date 1 is " + date1_use);
        if (month2 == 0 || month2 == 2 || month2 == 4
                || month2 == 6 || month2 == 7 || month2 == 9 || month2 == 11) {
            date2_use = new Date(Integer.valueOf(year2), Integer.valueOf(month2), 31);
        } else if (month2 == 3 || month2 == 5 || month2 == 8 || month2 == 10) {
            date2_use = new Date(Integer.valueOf(year2), Integer.valueOf(month2), 30);
        } else if (month2 == 1 && !isLeap(Integer.valueOf(year2))) {
            date2_use = new Date(Integer.valueOf(year2), Integer.valueOf(month2), 28);
        } else {
            date2_use = new Date(Integer.valueOf(year2), Integer.valueOf(month2), 29);
        }
        System.out.println("Date 2 is " + date2_use);

        Double allCount = 0.0;
        int bookingAllCount = 0;
        CartesianChartModel cartesianModel1 = new CartesianChartModel();
        CartesianChartModel cartesianModel2 = new CartesianChartModel();
        ChartSeries revenue = new ChartSeries();
        ChartSeries booking = new ChartSeries();
        revenue.setLabel("revenue");
        booking.setLabel("booking");
        System.out.println("C");
        List<BranchEntity> branch = new ArrayList<BranchEntity>();
        branch = branchSessionBean.getAllBranchByStakeholderId(selectedStakeholder.getId());
        while (date1_use.compareTo(date2_use) <= 0) {
            System.out.println("D");
            int numberOfDay = getMaxDayOfMonth(date1_use.getMonth(), date1_use.getYear() + 1900);
            String month = String.valueOf(date1_use.getMonth() + 1);
            String year = String.valueOf(date1_use.getYear() + 1900);
            for (int i = 1; i <= numberOfDay; i++) {
                System.out.println("E");
                int countBooking = 0;
                Double countRevenue = 0.0; //revenue of one stakeholder               
                for (BranchEntity b : branch) {
                    System.out.println("F");
                    //add up each branch revenue
                    if (b instanceof FnBBranchEntity) {
                        System.out.println("G");
                        FnBBranchEntity f = (FnBBranchEntity) b;
                        List<FnBReservationEntity> fnBReservation = new ArrayList<FnBReservationEntity>();
                        List<String> reservationNumbers = new ArrayList<String>();
                        fnBReservation = metricSessionBean.dateReservation(date1_use, f.getId());
                        reservationNumbers = metricSessionBean.reservationNumbers(fnBReservation);

                        System.out.println("reservationNumbers.get(6) " + reservationNumbers.get(6));
                        System.out.println("reservationNumbers.get(0) " + reservationNumbers.get(0));

                        countRevenue = countRevenue + Double.valueOf(reservationNumbers.get(6));
                        countBooking = countBooking + Integer.valueOf(reservationNumbers.get(0));
                    }
                }
                allCount = allCount + countRevenue;
                bookingAllCount = bookingAllCount + countBooking;
                System.out.println("allCount: " + allCount);
                System.out.println("bookingAllCount: " + bookingAllCount);
                date1_use.setTime(date1_use.getTime() + 1 * 24 * 60 * 60 * 1000);
            }
            revenue.set(month + ", " + year, allCount);
            booking.set(month + ", " + year, bookingAllCount);
            allCount = 0.0;
            bookingAllCount = 0;
        }
        cartesianModel1.addSeries(revenue);
        cartesianModel2.addSeries(booking);
        // 0: booking growth
        //1: revenue growth


        if (currentValue == 0) {
            metric.setModel(cartesianModel2);
        } else {
            metric.setModel(cartesianModel1);
        }
        System.out.println("Finish method");

    }

    //Returning Rate
    private void initReturningRate(long id) {
        MetricHelper metric = metricMap.get(id);
        metric.setCompute(true);
        if (!metric.isInit()) {
            metric.addDateList("From ");
            metric.addDateList("To  ");
            List selectList;
            selectList = new ArrayList<SelectItem>();
            selectList.add(new SelectItem(0, "Tourist "));
            selectList.add(new SelectItem(1, "Local "));
            metric.addSelectList(selectList, "Type of Customer");

            metric.setInit(true);
        }
    }

    private void computeReturningRate(long id) {
        MetricHelper metric = metricMap.get(id);
        Date date1 = metric.getDateList();
        Date date2 = metric.getDateList();
        int currentValue = metric.getSelectVar();

        PieChartModel touristReturning = new PieChartModel();
        PieChartModel localReturning = new PieChartModel();
        List<String> returningRate = new ArrayList<String>();

        //start-tourist
        List<TouristAccountEntity> touristList = new ArrayList<TouristAccountEntity>();
        touristList = touristSessionBean.getTouristAccountOfStakeholder(selectedStakeholder, date1, date2);

        List<TouristAccountEntity> touristList1 = new ArrayList<TouristAccountEntity>(); //for tourist come 1 time
        List<TouristAccountEntity> touristList2 = new ArrayList<TouristAccountEntity>(); // for toursits come 2 times and above

        for (TouristAccountEntity t : touristList) {
            if (!touristList1.contains(t) && !touristList2.contains(t)) {
                touristList1.add(t);
            } else if (touristList1.contains(t) && !touristList2.contains(t)) {
                touristList2.add(t);
                touristList1.remove(t);
            } else if (!touristList1.contains(t) && touristList2.contains(t)) {
            }
        }

        Double touristRate = 0.0;
        if (!touristList1.isEmpty() || !touristList2.isEmpty()) {
            touristRate = (Double) (touristList2.size() * 1.0) / (touristList1.size() + touristList2.size());
            touristRate = roundTwoDecimals(touristRate);
        }
        returningRate.add(String.valueOf(touristList2.size()));
        returningRate.add(touristRate.toString());
        touristReturning.set("Returning Tourists", touristList2.size());
        touristReturning.set("Not Returning Toursits", touristList1.size());
        //end-tourist

        //start-local
        List<TouristAccountEntity> localList = touristSessionBean.getLocalAccountOfStakeholder(selectedStakeholder, date1, date2);

        List<TouristAccountEntity> localList1 = new ArrayList<TouristAccountEntity>();
        List<TouristAccountEntity> localList2 = new ArrayList<TouristAccountEntity>();

        for (TouristAccountEntity t : localList) {
            if (!localList1.contains(t) && !localList2.contains(t)) {
                localList1.add(t);
            } else if (localList1.contains(t) && !localList2.contains(t)) {
                localList2.add(t);
                localList1.remove(t);
            } else if (!localList1.contains(t) && localList2.contains(t)) {
            }
        }

        Double localRate = 0.0;

        if (!localList1.isEmpty() || !localList2.isEmpty()) {
            localRate = (Double) (localList2.size() * 1.0) / (localList1.size() + localList2.size());
            localRate = roundTwoDecimals(localRate);
        }

        returningRate.add(String.valueOf(localList2.size()));
        returningRate.add(localRate.toString());
        localReturning.set("Returning Local Customers", localList2.size());
        localReturning.set("Not Returning Local Customers", localList1.size());
        //end-local
        // 0: Tourist
        //1: Local
        if (currentValue == 0) {
            if (touristList1.isEmpty()) {
                metric.resetOutputValue();
                metric.addOutputValue("", "There is no Tourist customers coming in this period");
                metric.setModel(null);
            } else {
                metric.resetOutputValue();
                metric.addOutputValue("Number of returning Tourists: ", returningRate.get(0));
                metric.addOutputValue("Tourist returning rate: ", returningRate.get(1));
                metric.setModel(touristReturning);
            }
        } else {
            if (localList1.isEmpty()) {
                metric.resetOutputValue();
                metric.addOutputValue("", "There is no Local customers coming in this period");
                metric.setModel(null);
            } else {
                metric.resetOutputValue();
                metric.addOutputValue("Number of returning Local customers: ", returningRate.get(2));
                metric.addOutputValue("Local returning rate: ", returningRate.get(3));
                metric.setModel(localReturning);
            }
        }
    }

    //Upselling Rate
    private void initUpsellingRate(long id) {
        MetricHelper metric = metricMap.get(id);
        if (!metric.isInit()) {
            Double touristUpsellingRate = 0.0;
            Double localUpsellingRate = 0.0;
            int countTourist = 0, countLocal = 0;
            Double sumTourist = 0.0, sumLocal = 0.0;
            List<TouristAccountEntity> returneeList = new ArrayList<TouristAccountEntity>();
            System.out.println("1");
            returneeList = touristSessionBean.getReturneeOfStakeholder(selectedStakeholder);
            System.out.println("2");
            for (TouristAccountEntity t : returneeList) {
                if (t.getTourist().getCountry() == Country.SINGAPORE) {
                    System.out.println("3A");
                    countLocal++;
                    sumLocal = sumLocal + metricSessionBean.getUpsellingRate(t, selectedStakeholder);
                    System.out.println("3B");
                } else {
                    System.out.println("4A");
                    countTourist++;
                    sumTourist = sumTourist + metricSessionBean.getUpsellingRate(t, selectedStakeholder);
                    System.out.println("coutTourist " + countTourist);
                    System.out.println("sumTourist " + sumTourist);
                }
            }
            System.out.println("AAAAAAAAAAAAAa " + countTourist);
            System.out.println("AAAAAAAAAAAAAa " + countLocal);
            if (countLocal != 0) {
                localUpsellingRate = roundTwoDecimals(sumLocal / countLocal);
            }
            if (countTourist != 0) {
                touristUpsellingRate = roundTwoDecimals(sumTourist / countTourist);
            }

            metric.addOutputValue("Tourist Customer Upselling Rate: ", touristUpsellingRate.toString());
            metric.addOutputValue("Local Customer Upselling Rate: ", localUpsellingRate.toString());
            metric.setInit(true);
        }
    }

    Double roundTwoDecimals(Double d) {
        DecimalFormat twoDForm = new DecimalFormat("#.##");
        return Double.valueOf(twoDForm.format(d));
    }

    public boolean isLeap(int year) {
        return ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
    }

    private int getMaxDayOfMonth(int month, int year) {
        switch (month) {
            case 0:
            case 2:
            case 4:
            case 6:
            case 7:
            case 9:
            case 11:
                return 31;
            case 1:
                if (isLeap(year)) {
                    return 29;
                } else {
                    return 28;
                }
            default:
                return 30;
        }
    }
    /*Hieu end Nov 1
     * 
     */
}
